home *** CD-ROM | disk | FTP | other *** search
- /* Parse command line, set up command arguments Unix-style, and call function.
- * Note: argument is modified (delimiters are overwritten with nulls)
- *
- * Copyright 1991 Phil Karn, KA9Q
- *
- * Improved error handling by Brian Boesch of Stanford University
- * Feb '91 - Bill Simpson
- * bit16cmd for PPP
- * Mar '91 - Glenn McGregor
- * handle string escaped sequences
- */
- #include <stdio.h>
- #include <ctype.h>
- #ifdef MSDOS
- #include <conio.h>
- #endif
- #include "global.h"
- #include "config.h"
- #include "proc.h"
- #include "cmdparse.h"
- #include "session.h"
- #include "pktdrvr.h"
- #include "iface.h"
- #include "socket.h"
-
- struct boolcmd {
- char *str; /* Token */
- int val; /* Value */
- };
-
- static struct boolcmd Boolcmds[] = {
- "y", 1, /* Synonyms for "true" */
- "yes", 1,
- "true", 1,
- "on", 1,
- "1", 1,
- "set", 1,
- "enable", 1,
-
- "n", 0, /* Synonyms for "false" */
- "no", 0,
- "false", 0,
- "off", 0,
- "0", 0,
- "clear", 0,
- "disable", 0,
- NULLCHAR
- };
-
- static char *stringparse __ARGS((char *line));
-
- static char *
- stringparse(line)
- char *line;
- {
- register char *cp = line;
- unsigned long num;
-
- while ( *line != '\0' && *line != '\"' ) {
- if ( *line == '\\' ) {
- line++;
- switch ( *line++ ) {
- case 'n':
- *cp++ = '\n';
- break;
- case 't':
- *cp++ = '\t';
- break;
- case 'v':
- *cp++ = '\v';
- break;
- case 'b':
- *cp++ = '\b';
- break;
- case 'r':
- *cp++ = '\r';
- break;
- case 'f':
- *cp++ = '\f';
- break;
- case 'a':
- #ifdef __STDC__
- *cp++ = '\a';
- #else
- *cp++ = '\007';
- #endif
- break;
- case '\\':
- *cp++ = '\\';
- break;
- case '\?':
- *cp++ = '\?';
- break;
- case '\'':
- *cp++ = '\'';
- break;
- case '\"':
- *cp++ = '\"';
- break;
- case 'x':
- num = strtoul( --line, &line, 16 );
- *cp++ = (char) num;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- num = strtoul( --line, &line, 8 );
- *cp++ = (char) num;
- break;
- case '\0':
- return NULLCHAR;
- default:
- *cp++ = *(line - 1);
- break;
- };
- } else {
- *cp++ = *line++;
- }
- }
-
- if ( *line == '\"' )
- line++; /* skip final quote */
- *cp = '\0'; /* terminate string */
- return line;
- }
-
- #ifdef LOCK
- int Kblocked;
- char *Kbpasswd;
- #endif
-
- int
- cmdparse(cmds,line,p)
- struct cmds cmds[];
- register char *line;
- void *p;
- {
- struct cmds *cmdp;
- char *argv[NARG],*cp;
- char **pargv;
- int argc,i;
-
- /* Remove cr/lf */
- rip(line);
-
- for(argc = 0;argc < NARG;argc++)
- argv[argc] = NULLCHAR;
-
- for(argc = 0;argc < NARG;){
- register int qflag = FALSE;
-
- /* Skip leading white space */
- while(*line == ' ' || *line == '\t')
- line++;
- if(*line == '\0')
- break;
- /* return if comment character first non-white */
- if ( argc == 0 && *line == '#' )
- return 0;
- /* Check for quoted token */
- if(*line == '"'){
- line++; /* Suppress quote */
- qflag = TRUE;
- }
- argv[argc++] = line; /* Beginning of token */
-
- if(qflag){
- /* Find terminating delimiter */
- if((line = stringparse(line)) == NULLCHAR){
- return -1;
- }
- } else {
- /* Find space or tab. If not present,
- * then we've already found the last
- * token.
- */
- #ifdef old
- if((cp = strchr(line,' ')) == NULLCHAR
- && (cp = strchr(line,'\t')) == NULLCHAR){
- break;
- }
- #endif
- for(cp=line;*cp;cp++) {
- if(*cp == ' ' || *cp == '\t')
- break;
- }
- /* if we didn't reach end of line yet, cutoff this arg here */
- if(*cp == '\0')
- break;
- *cp++ = '\0';
- line = cp;
- }
- }
- if (argc < 1) { /* empty command line */
- argc = 1;
- argv[0] = "";
- }
-
- #ifdef LOCK
- /* Check to see if this is the Command session.
- * If so, check to see if the keyboard is locked
- * Added 12/12/91 WG7J
- */
- if(Curproc->input == Command->input)
- if(Kblocked) { /*check argv[0] for password!*/
- if(strcmp(argv[0],Kbpasswd)) {
- tputs("\nKeyboard remains locked\n");
- return 0;
- }
- Command->ttystate.echo = 1; /* turn character echo back on ! */
- Kblocked=0; /* correct password, so unlock */
- return 0;
- }
- #endif
-
- /* Look up command in table; prefix matches are OK */
- /* Not case sensitive anymore - WG7J */
- for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
- if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0)
- break;
- }
- if(cmdp->name == NULLCHAR) {
- if(cmdp->argc_errmsg != NULLCHAR)
- tprintf("%s\n",cmdp->argc_errmsg);
- return -1;
- } else {
- if(argc < cmdp->argcmin) {
- /* Insufficient arguments */
- tprintf("Usage: %s\n",cmdp->argc_errmsg);
- return -1;
- } else {
- if(cmdp->stksize == 0){
- return (*cmdp->func)(argc,argv,p);
- } else {
- /* Make private copy of argv and args,
- * spawn off subprocess and return.
- */
- pargv = (char **)callocw((unsigned)argc,sizeof(char *));
- for(i=0;i<argc;i++)
- pargv[i] = strdup(argv[i]);
- newproc(cmdp->name,(unsigned)cmdp->stksize,
- (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
- return(0);
- }
- }
- }
- }
-
- /* Call a subcommand based on the first token in an already-parsed line */
- int
- subcmd(tab,argc,argv,p)
- struct cmds tab[];
- int argc;
- char *argv[];
- void *p;
- {
- register struct cmds *cmdp;
- char **pargv;
- int found = 0;
- int i;
-
- /* Strip off first token and pass rest of line to subcommand */
- if (argc < 2) {
- if (argc < 1)
- tprintf("SUBCMD - Don't know what to do?\n");
- else
- tprintf("\"%s\" - takes at least one argument\n",argv[0]);
- return -1;
- }
- argc--;
- argv++;
- for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
- /* Not case sensitive anymore - WG7J */
- if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0){
- found = 1;
- break;
- }
- }
- if(!found){
- tprintf("valid subcommands:");
- for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
- if(tprintf(" %s",cmdp->name) == EOF)
- return -1;
- tprintf("\n");
- return -1;
- }
- if(argc < cmdp->argcmin){
- if(cmdp->argc_errmsg != NULLCHAR)
- tprintf("Usage: %s\n",cmdp->argc_errmsg);
- return -1;
- }
- if(cmdp->stksize == 0){
- return (*cmdp->func)(argc,argv,p);
- } else {
- /* Make private copy of argv and args */
- pargv = (char **)callocw((unsigned)argc,sizeof(char *));
- for(i=0;i<argc;i++)
- pargv[i] = strdup(argv[i]);
- newproc(cmdp->name,(unsigned)cmdp->stksize,
- (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
- return(0);
- }
- }
-
- /* Subroutine for setting and displaying boolean flags */
- int
- setbool(var,label,argc,argv)
- int *var;
- char *label;
- int argc;
- char *argv[];
- {
- struct boolcmd *bc;
-
- if(argc < 2){
- tprintf("%s: %s\n",label,*var ? "on":"off");
- return 1;
- }
- for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
- if(strcmpi(argv[1],bc->str) == 0){
- *var = bc->val;
- return 0;
- }
- }
- tprintf("Valid options:");
- for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
- if(tprintf(" %s",bc->str) == EOF)
- return 1;
- tprintf("\n");
- return 1;
- }
-
-
- /* Subroutine for setting and displaying bit values */
- int
- bit16cmd(bits,mask,label,argc,argv)
- int16 *bits;
- int16 mask;
- char *label;
- int argc;
- char *argv[];
- {
- int doing = (*bits & mask);
- int result = setbool( &doing, label, argc, argv );
-
- if ( !result ) {
- if ( doing )
- *bits |= mask;
- else
- *bits &= ~mask;
- }
- return result;
- }
-
-
- /* Subroutine for setting and displaying long variables */
- int
- setlong(var,label,argc,argv)
- long *var;
- char *label;
- int argc;
- char *argv[];
- {
- if(argc < 2){
- tprintf("%s: %ld\n",label,*var);
- return 1;
- } else {
- *var = atol(argv[1]);
- return 0;
- }
-
- }
- /* Subroutine for setting and displaying short variables */
- int
- setshort(var,label,argc,argv)
- unsigned short *var;
- char *label;
- int argc;
- char *argv[];
- {
- if(argc < 2){
- tprintf("%s: %u\n",label,*var);
- return 1;
- } else {
- *var = atoi(argv[1]);
- return 0;
- }
- }
- /* Subroutine for setting and displaying integer variables */
- int
- setint(var,label,argc,argv)
- int *var;
- char *label;
- int argc;
- char *argv[];
- {
- if(argc < 2){
- tprintf("%s: %i\n",label,*var);
- return 1;
- } else {
- *var = atoi(argv[1]);
- return 0;
- }
-
- }
-
- /* Subroutine for setting and displaying unsigned integer variables */
- int
- setuns(var,label,argc,argv)
- unsigned *var;
- char *label;
- int argc;
- char *argv[];
- {
- if(argc < 2){
- tprintf("%s: %u\n",label,*var);
- return 1;
- } else {
- *var = atoi(argv[1]);
- return 0;
- }
- }
-
- /* Subroutine for setting and displaying int variables (with range check) */
- int
- setintrc(var, label, argc, argv, minval, maxval)
- int16 *var;
- char *label;
- int argc;
- char *argv[];
- int minval;
- int16 maxval;
- {
- int tmp;
-
- if (argc < 2)
- tprintf("%s: %u\n", label, *var);
- else {
- tmp = atoi(argv[1]);
- if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
- tprintf("%s must be %i..%i\n", label, minval, maxval);
- return 1;
- }
- *var = (int16)tmp;
- }
- return 0;
- }
-
- /* Set flags on ax.25 interfaces - WG7J */
-
- int setflag(int argc,char *ifname,long flag,char *cmd) {
- struct iface *ifp;
- struct boolcmd *bc;
-
- if(argc == 1) {
- for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
- if(ifp->flags & flag)
- tprintf("%s\n",ifp->name);
- } else {
- if((ifp = if_lookup(ifname)) == NULLIF){
- tprintf(Badinterface,ifname);
- return 1;
- }
- /*
- if(ifp->type != CL_AX25) {
- tputs("not an AX.25 interface\n");
- return 1;
- }
- */
- if(argc == 2) {
- /* Show the value of the flag */
- if(ifp->flags & flag)
- tputs("On\n");
- else
- tputs("Off\n");
- } else {
- for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
- if(strcmpi(cmd,bc->str) == 0){
- if(bc->val)
- ifp->flags |= flag;
- else
- ifp->flags &= ~flag;
- return 0;
- }
- /* Invalid option ! */
- tputs("Valid options:");
- for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
- if(tprintf(" %s",bc->str) == EOF)
- return 1;
- tputc('\n');
- }
- }
- return 0;
- }
-
-
-